package com.tingyuge.thinking.spring.dependency.lookup;

import com.tingyuge.thinking.spring.ioc.overview.domain.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author xiaodao
 * @version 1.0
 * @date 2021/6/27
 */
public class HierarchicalDependencyLookupDemo {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        //注册 configuration class（配置类）
        applicationContext.register(ObjectProviderDemo.class);

        //1. 获取HierarchicalBeanFactory <-----ConfigurableBeanFactory<-ConfigurableListableBeanFactory
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
//        System.out.println("当前beanFactory 的parent BeanFactory: " + beanFactory.getParentBeanFactory());
        //2. 设置 parent beanFactory
        HierarchicalBeanFactory parentBeanFactory = createParentBeanFactory();
        beanFactory.setParentBeanFactory(parentBeanFactory);
//        System.out.println(beanFactory.getParentBeanFactory());
        //启动应用上下文
        displayLocalBean(beanFactory, "user");
        displayLocalBean(parentBeanFactory, "user");
        System.out.println();
        displayContainsBean(beanFactory, "user");
        displayContainsBean(parentBeanFactory, "user");
        applicationContext.refresh();
    }

    private static void displayContainsBean(HierarchicalBeanFactory beanFactory, String beanName) {
        System.out.printf("当前BeanFactory [%s] 是否包含: Local bean [name: %s] : %s \n", beanFactory, beanName,  containsBean(beanFactory,beanName));

    }

    /**
     * 一直找到parent 到顶层.实现类似双亲委派的模式
     * @param beanFactory
     * @param beanName
     * @return
     */
    private static boolean containsBean(HierarchicalBeanFactory beanFactory, String beanName) {
        BeanFactory parentBeanFactory = beanFactory.getParentBeanFactory();
        if (parentBeanFactory instanceof HierarchicalBeanFactory) {
            HierarchicalBeanFactory hierarchicalBeanFactory = HierarchicalBeanFactory.class.cast(parentBeanFactory);
            if (containsBean(hierarchicalBeanFactory, beanName)) {

                return true;
            }
        }
        return beanFactory.containsLocalBean(beanName);
    }

    private static void displayLocalBean(HierarchicalBeanFactory beanFactory, String beanName) {
        System.out.printf("当前BeanFactory [%s] 是否包含: Local bean [name: %s] : %s \n", beanFactory, beanName, beanFactory.containsLocalBean(beanName));


    }

    private static HierarchicalBeanFactory createParentBeanFactory() {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        //加载配置
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        //XML 配置文件ClassPath路径
        String location = "classpath:/META-INF/dependency-lookup-context.xml";
        int beanDefinitions = reader.loadBeanDefinitions(location);
        return beanFactory;
    }
}
